package utils

import (
	"github.com/golang-jwt/jwt/v5"
	"time"
)

var (
	jwtAccessSecret  = []byte("your-access-secret-key")  // 用于签发访问令牌
	jwtRefreshSecret = []byte("your-refresh-secret-key") // 用于签发刷新令牌
)

type Claims struct {
	UserCode  string   `json:"user_code"`
	Username  string   `json:"username"`
	Roles     []string `json:"roles"`      // 用户角色列表
	TokenType string   `json:"token_type"` // 令牌类型：access 或 refresh
	jwt.RegisteredClaims
}

// TokenPair 包含访问令牌和刷新令牌
type TokenPair struct {
	AccessToken  string `json:"access_token"`
	RefreshToken string `json:"refresh_token"`
}

// GenerateTokenPair 生成访问令牌和刷新令牌对
func GenerateTokenPair(userCode string, username string, roles []string) (*TokenPair, error) {
	// 生成访问令牌
	accessToken, err := generateAccessToken(userCode, username, roles)
	if err != nil {
		return nil, err
	}

	// 生成刷新令牌
	refreshToken, err := generateRefreshToken(userCode, username, roles)
	if err != nil {
		return nil, err
	}

	return &TokenPair{
		AccessToken:  accessToken,
		RefreshToken: refreshToken,
	}, nil
}

// generateAccessToken 生成访问令牌
func generateAccessToken(userCode string, username string, roles []string) (string, error) {
	claims := Claims{
		UserCode:  userCode,
		Username:  username,
		Roles:     roles,
		TokenType: "access",
		RegisteredClaims: jwt.RegisteredClaims{
			ExpiresAt: jwt.NewNumericDate(time.Now().Add(12 * time.Hour)), // 半天后过期
			IssuedAt:  jwt.NewNumericDate(time.Now()),
			NotBefore: jwt.NewNumericDate(time.Now()),
		},
	}

	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	return token.SignedString(jwtAccessSecret)
}

// generateRefreshToken 生成刷新令牌
func generateRefreshToken(userCode string, username string, roles []string) (string, error) {
	claims := Claims{
		UserCode:  userCode,
		Username:  username,
		Roles:     roles,
		TokenType: "refresh",
		RegisteredClaims: jwt.RegisteredClaims{
			ExpiresAt: jwt.NewNumericDate(time.Now().Add(7 * 24 * time.Hour)), // 7天后过期
			IssuedAt:  jwt.NewNumericDate(time.Now()),
			NotBefore: jwt.NewNumericDate(time.Now()),
		},
	}

	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	return token.SignedString(jwtRefreshSecret)
}

// ParseAccessToken 解析访问令牌
func ParseAccessToken(tokenString string) (*Claims, error) {
	return parseToken(tokenString, jwtAccessSecret)
}

// ParseRefreshToken 解析刷新令牌
func ParseRefreshToken(tokenString string) (*Claims, error) {
	return parseToken(tokenString, jwtRefreshSecret)
}

// parseToken 解析JWT令牌
func parseToken(tokenString string, secret []byte) (*Claims, error) {
	token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) {
		return secret, nil
	})

	if err != nil {
		return nil, err
	}

	if claims, ok := token.Claims.(*Claims); ok && token.Valid {
		return claims, nil
	}

	return nil, jwt.ErrSignatureInvalid
}

// RefreshTokens 使用刷新令牌获取新的令牌对
func RefreshTokens(refreshToken string) (*TokenPair, error) {
	// 解析刷新令牌
	claims, err := ParseRefreshToken(refreshToken)
	if err != nil {
		return nil, err
	}

	// 验证令牌类型
	if claims.TokenType != "refresh" {
		return nil, jwt.ErrTokenInvalidClaims
	}

	// 生成新的令牌对
	return GenerateTokenPair(claims.UserCode, claims.Username, claims.Roles)
}
